﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynaPrecision.Numerical
{
	public class SimpsonIntegrator
	{
		public const int DefaultSectionCount = 10;
		public static TResult Integrate<TInput, TResult>(TInput _leftBound, TInput rightBound, Func<TInput, TResult> func, int sectionCount = DefaultSectionCount)
		{
			TResult result = DynaPrecision.DefaultValueProvider<TResult>.Zero;
			TInput leftBound = _leftBound;
			TInput h = (rightBound - (dynamic)leftBound) / sectionCount / 2;
			result = result + (dynamic)func(leftBound);
			for (int i = 0; i < sectionCount - 1; i++)
			{
				leftBound = leftBound + (dynamic)h;
				result = result + (dynamic)func(leftBound) * 4.0;
				leftBound = leftBound + (dynamic)h;
				result = result + (dynamic)func(leftBound) * 2.0;
			}
			result = result + (dynamic)func(leftBound + (dynamic)h) * 4.0;
			result = result + (dynamic)func(rightBound);
			return result * (dynamic)h / 3.0;
		}
		public static TResult Integrate<TInput, TResult>(TInput _leftBound, TInput rightBound, FunctionAnalysis.IFunction<TInput, TResult> func, int sectionCount = DefaultSectionCount)
		{
			return SimpsonIntegrator.Integrate<TInput,TResult>(_leftBound, rightBound, func.Functor, sectionCount);
		}
		public static List<T> GetCoefficients<T>(int valueCount)
		{
			
			if (valueCount % 2 == 0)
			{
				List<T> result = new List<T>(GetCoefficients<T>(valueCount - 1));
				result[result.Count - 1] = result[result.Count - 1] + (dynamic)3.0 / 2;
				result.Add((dynamic)3.0 / 2);
				return result;
			}
			else
			{
				return _getCoefficients<T>((valueCount - 1) / 2).ToList();
			}

		}
		private static IEnumerable<T> _getCoefficients<T>(int doubleSectionCount)
		{
			yield return (dynamic)1;
			for (int i = 0; i < doubleSectionCount - 1; i++)
			{
				yield return (dynamic)4;
				yield return (dynamic)2;
			}
			yield return (dynamic)4;
			yield return (dynamic)1;
		}
	}
}
